package rede.treinamento;

import static jogo.SimboloJogada.X;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import jogo.SimboloJogada;
import jogo.Tabuleiro;

public class GeradorConjuntoTreinamento {

	private static List<String> lines = new LinkedList<String>();
	private StringBuilder line;

	private static final SimboloJogada DEFAULT = X;

	public GeradorConjuntoTreinamento() {
	}

	public void gera(int numJogadas, int numCasos) {
		for (int k = 0; k < numCasos; k++) {
			Tabuleiro tab = makeTabuleiroAleatorio(numJogadas);

			Double[][] scores = CalculadorScore.calculaScores(tab, X);

			line = new StringBuilder();
			makeLineToPrint(tab, scores);
			lines.add(line.toString());
		}
	}

	private void makeLineToPrint(Tabuleiro tab, Double[][] scores) {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (scores[i][j].equals(Double.NaN))
					continue;
				printTabuleiro(tab);
				printCasaTabuleiro(i, j);
				NumberFormat nf = DecimalFormat.getInstance(Locale.US);
				nf.setMaximumFractionDigits(4);
				line.append(nf.format(scores[i][j]));
				line.append(";");
				line.append("\n");
			}
		}
	}

	private void printCasaTabuleiro(int a, int b) {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (i == a && j == b)
					line.append("1");
				else
					line.append("0");
				line.append(";");
			}
		}
	}

	private void printTabuleiro(Tabuleiro tab) {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				line.append(tab.getSimbolo(i, j).getValue());
				line.append(";");
			}
		}
	}

	private Tabuleiro makeTabuleiroAleatorio(int numJogadas) {
		Tabuleiro tab = new Tabuleiro();
		List<Integer> domain = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8);
		List<Integer> casas = domain.subList(0, numJogadas);
		Collections.shuffle(domain, new Random());

		int i;
		for (i = 0; i < numJogadas - 1; i += 2) {
			int casaDefault = casas.get(i);
			tab.setSimbolo(casaDefault / 3, casaDefault % 3, DEFAULT);
			int casaOposto = casas.get(i + 1);
			tab.setSimbolo(casaOposto / 3, casaOposto % 3, DEFAULT.contrario());
		}

		if (i < numJogadas) {
			int casaDefault = casas.get(i);
			tab.setSimbolo(casaDefault / 3, casaDefault % 3, DEFAULT);
		}

		return tab;
	}
	
	public void gera(int n) {
		int[] array = new int[n];
		geraArvore(array, 0, n);
	}

	public void geraArvore(int[] atual, int i, int n) {
		if (i == n) {
			processa(atual);
			return;
		}

		for (int k = 0; k < 9; k++) {
			boolean pula = false;
			for (int j = 0; j < i && !pula; j++) {
				if (atual[j] == k)
					pula = true;
			}
			if (!pula) {
				atual[i] = k;
				geraArvore(atual, i+1, n);
			}
		}
	}

	private void processa(int[] atual) {
		Tabuleiro tab = makeTabuleiro(atual);
		Double[][] scores = CalculadorScore.calculaScores(tab, X);
		line = new StringBuilder();
		makeLineToPrint(tab, scores);
		lines.add(line.toString());
	}

	private Tabuleiro makeTabuleiro(int[] atual) {
		Tabuleiro tab = new Tabuleiro();
		for (int i = 0; i < atual.length; i++) {
			tab.setSimbolo(atual[i]/3, atual[i]%3, i%2==0 ? SimboloJogada.O : SimboloJogada.X);
		}
		return tab;
	}

	public static void main(String[] args) {
		GeradorConjuntoTreinamento gerador = new GeradorConjuntoTreinamento();
//		gerador.gera(2);

		 gerador.gera(2, 30); // max = 72 x 8
		 gerador.gera(4, 300); // max = 756 x 8
		 gerador.gera(6, 200); // max = 1680 x 8
//		 gerador.gera(8, 50); // max = 630 x 8

		 Collections.shuffle(lines);

		for (String line : lines) {
			System.out.print(line);
		}
	}

}
